package com.shengyuan.manage_os.old.ying.erpm.device;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Handler;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Set;
import java.util.UUID;

public class BlueToothService
{
  private BluetoothAdapter adapter;
  private Context context;
  private int mState;
  private int scanState = 1;
  private Boolean D = Boolean.valueOf(true);
  private String TAG = "BlueToothService";
  private AcceptThread mAcceptThread;
  private ConnectThread mConnectThread;
  private ConnectedThread mConnectedThread;
  public static final int STATE_NONE = 0;
  public static final int STATE_LISTEN = 1;
  public static final int STATE_CONNECTING = 2;
  public static final int STATE_CONNECTED = 3;
  public static final int LOSE_CONNECT = 4;
  public static final int FAILED_CONNECT = 5;
  public static final int SUCCESS_CONNECT = 6;
  public static final int MESSAGE_STATE_CHANGE = 1;
  public static final int MESSAGE_READ = 2;
  public static final int MESSAGE_WRITE = 3;
  public static final int STATE_SCANING = 0;
  public static final int STATE_SCAN_STOP = 1;
  private static final int WRITE_READ = 2;
  private static final int WRITE_WAIT = 3;
  private static int writeState = 2;
  public static int times = 0;
  private static int PrinterType = 0;
  private static int PrinterTypeNow = 0;
  private int timeout;
  private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
  private static final String NAME = "BTPrinter";
  private Handler mHandler;
  public OnReceiveDataHandleEvent OnReceive = null;

  private final BroadcastReceiver mReceiver = new BroadcastReceiver()
  {
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();

      if ("android.bluetooth.device.action.FOUND".equals(action))
      {
        BluetoothDevice device = 
          (BluetoothDevice)intent
          .getParcelableExtra("android.bluetooth.device.extra.DEVICE");

        if (device.getBondState() != 12) {
          BlueToothService.this.SetScanState(0);
          BlueToothService.this.OnReceive.OnReceive(device);
        }

      }
      else if ("android.bluetooth.adapter.action.DISCOVERY_FINISHED"
        .equals(action)) {
        BlueToothService.this.SetScanState(1);

        BlueToothService.this.OnReceive.OnReceive(null);
      }
    }

    private void OnFinished()
    {
    }
  };

  public static String EXTRA_DEVICE_ADDRESS = "device_address";

  private void SetWriteState(int state)
  {
    synchronized (this) {
      writeState = state;
    }
  }

  public BlueToothService(Context context, Handler handler)
  {
    this.context = context;
    this.mHandler = handler;
    this.mState = 0;
    this.adapter = BluetoothAdapter.getDefaultAdapter();
  }

  public boolean HasDevice()
  {
    return this.adapter != null;
  }

  public boolean IsOpen()
  {
    synchronized (this)
    {
      return this.adapter.isEnabled();
    }
  }

  public void OpenDevice()
  {
    Intent intent = new Intent("android.bluetooth.adapter.action.REQUEST_ENABLE");

    this.context.startActivity(intent);
  }

  public void CloseDevice()
  {
    this.adapter.disable();
  }

  public Set<BluetoothDevice> GetBondedDevice()
  {
    Set devices = this.adapter.getBondedDevices();
    return devices;
  }

  public void ScanDevice()
  {
    IntentFilter filter = new IntentFilter("android.bluetooth.device.action.FOUND");
    this.context.registerReceiver(this.mReceiver, filter);

    filter = new IntentFilter("android.bluetooth.adapter.action.DISCOVERY_FINISHED");
    this.context.registerReceiver(this.mReceiver, filter);
    if (this.adapter.isDiscovering()) {
      this.adapter.cancelDiscovery();
    }
    SetScanState(0);

    this.adapter.startDiscovery();
  }

  public void StopScan()
  {
    this.context.unregisterReceiver(this.mReceiver);
    this.adapter.cancelDiscovery();
    SetScanState(1);
  }

  public OnReceiveDataHandleEvent getOnReceive()
  {
    return this.OnReceive;
  }

  public void setOnReceive(OnReceiveDataHandleEvent onReceive) {
    this.OnReceive = onReceive;
  }

  public void ConnectToDevice(String address)
  {
    if (BluetoothAdapter.checkBluetoothAddress(address)) {
      BluetoothDevice device = this.adapter.getRemoteDevice(address);
      PrinterType = 0;
      PrinterTypeNow = 0;
      connect(device);
    }
  }

  public void write(byte[] out)
  {
    ConnectedThread r;
    synchronized (this) {
      if (this.mState != 3)
        return;
      r = this.mConnectedThread;
    }
    r.write(out);
  }

  public synchronized void start() {
    if (this.D.booleanValue()) {
      Log.d(this.TAG, "start");
    }

    if (this.mConnectThread != null) {
      this.mConnectThread.cancel();
      this.mConnectThread = null;
    }

    if (this.mConnectedThread != null) {
      this.mConnectedThread.cancel();
      this.mConnectedThread = null;
    }

    if (this.mAcceptThread == null) {
      this.mAcceptThread = new AcceptThread();
      this.mAcceptThread.start();
    }
    setState(1);
  }

  private synchronized void setState(int state) {
    this.mState = state;
  }

  public synchronized int getState() {
    return this.mState;
  }

  private synchronized void SetScanState(int state)
  {
    this.scanState = state;
  }

  public synchronized int GetScanState() {
    return this.scanState;
  }

  public synchronized void connect(BluetoothDevice device)
  {
    if ((this.mState == 2) && 
      (this.mConnectThread != null)) {
      this.mConnectThread.cancel();
      this.mConnectThread = null;
    }

    if (this.mConnectedThread != null) {
      this.mConnectedThread.cancel();
      this.mConnectedThread = null;
    }
    try {
      Thread.sleep(1000L);
    }
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    this.mConnectThread = new ConnectThread(device);
    this.mConnectThread.start();
    setState(2);
  }

  public synchronized void DisConnected()
  {
    if (this.mConnectThread != null) {
      this.mConnectThread.cancel();
      this.mConnectThread = null;
    }

    if (this.mConnectedThread != null) {
      this.mConnectedThread.cancel();
      this.mConnectedThread = null;
    }

    if (this.mAcceptThread != null) {
      this.mAcceptThread.cancel();
      this.mAcceptThread = null;
    }

    setState(0);
  }

  public synchronized void connected(BluetoothSocket socket, BluetoothDevice device)
  {
    if (this.mConnectThread != null) {
      this.mConnectThread.cancel();
      this.mConnectThread = null;
    }

    if (this.mConnectedThread != null) {
      this.mConnectedThread.cancel();
      this.mConnectedThread = null;
    }

    if (this.mAcceptThread != null) {
      this.mAcceptThread.cancel();
      this.mAcceptThread = null;
    }

    this.mConnectedThread = new ConnectedThread(socket);
    this.mConnectedThread.start();

    setState(3);
  }

  public synchronized void stop()
  {
    if (this.D.booleanValue())
      Log.d(this.TAG, "stop");
    setState(0);
    if (this.mConnectThread != null) {
      this.mConnectThread.cancel();
      this.mConnectThread = null;
    }
    if (this.mConnectedThread != null) {
      this.mConnectedThread.cancel();
      this.mConnectedThread = null;
    }
    if (this.mAcceptThread != null) {
      this.mAcceptThread.cancel();
      this.mAcceptThread = null;
    }
  }

  private void connectionSuccess() {
    setState(3);
    SetPrinterInf();
    this.mHandler.obtainMessage(1, 6, -1)
      .sendToTarget();
  }

  private void SetPrinterInf()
  {
    new Thread() {
      public void run() {
        try {
          Thread.sleep(200L);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        BlueToothService.PrinterTypeNow = BlueToothService.PrinterType;
      }
    }
    .start();
  }

  private void connectionFailed() {
    setState(1);
    this.mHandler.obtainMessage(1, 5, -1)
      .sendToTarget();
  }

  private void connectionLost()
  {
    setState(1);
    this.mHandler.obtainMessage(1, 4, -1)
      .sendToTarget();
  }

  public void SetPrinterType(int type)
  {
    PrinterType = type;
  }

  public void PrintCharacters(String str)
  {
    byte[] send;
    try
    {
      send = str.getBytes("GB2312");
    }
    catch (UnsupportedEncodingException e)
    {
      send = str.getBytes();
    }
    write(send);
  }

  public void SendOrder(byte[] send) {
    write(send);
  }

  public void PrintImage(Bitmap bitmapcode, int timeout) {
    this.timeout = timeout;
    if (PrinterTypeNow == 2) {
      PrintImageOld(bitmapcode);
    }
    else {

      System.out.println("********===" + PrinterTypeNow);
      PrintImageNew(bitmapcode);
    }
  }

  public void PrintImageOld(Bitmap bitmapCode)
  {
    int w = bitmapCode.getWidth();
    int h = bitmapCode.getHeight();
    byte[] sendbuf = StartBmpToPrintCode(bitmapCode);

    int num = 0;
    int total = 1152;

    while (num != sendbuf.length)
      if (writeState == 2)
      {
        byte[] sendper=null;
        if (sendbuf.length - num > total) {
          byte[] sendper1 = new byte[total];
          System.arraycopy(sendbuf, num, sendper1, 0, total);
          num += total;
        } else {
          sendper = new byte[sendbuf.length - num];
          System.arraycopy(sendbuf, num, sendper, 0, sendbuf.length - 
            num);
          num = sendbuf.length;
        }
        try {
          Thread.sleep(this.timeout);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        write(sendper);
      }
  }

  public void PrintImageNew(Bitmap bitmapCode)
  {
    int w = bitmapCode.getWidth();
    int h = bitmapCode.getHeight();
    byte[] sendbuf = StartBmpToPrintCode(bitmapCode);

    write(sendbuf);
  }

  private byte[] StartBmpToPrintCode(Bitmap bitmap)
  {
    byte temp = 0;
    int j = 7;
    int start = 0;
    if (bitmap != null) {
      int mWidth = bitmap.getWidth();
      int mHeight = bitmap.getHeight();

      int[] mIntArray = new int[mWidth * mHeight];
      byte[] data = new byte[mWidth * mHeight];
      bitmap.getPixels(mIntArray, 0, mWidth, 0, 0, mWidth, mHeight);
      encodeYUV420SP(data, mIntArray, mWidth, mHeight);
      byte[] result = new byte[mWidth * mHeight / 8];
      for (int i = 0; i < mWidth * mHeight; i++) {
        temp = (byte)((byte)(data[i] << j) + temp);
        j--;
        if (j < 0) {
          j = 7;
        }
        if (i % 8 == 7) {
          result[(start++)] = temp;
          temp = 0;
        }
      }
      if (j != 7) {
        result[(start++)] = temp;
      }

      int aHeight = 24 - mHeight % 24;
      int perline = mWidth / 8;
      byte[] add = new byte[aHeight * perline];
      byte[] nresult = new byte[mWidth * mHeight / 8 + aHeight * perline];
      System.arraycopy(result, 0, nresult, 0, result.length);
      System.arraycopy(add, 0, nresult, result.length, add.length);

      byte[] byteContent = new byte[(mWidth / 8 + 4) * (
        mHeight + aHeight)];
      byte[] bytehead = new byte[4];
      bytehead[0] = 31;
      bytehead[1] = 16;
      bytehead[2] = (byte)(mWidth / 8);
      bytehead[3] = 0;
      for (int index = 0; index < mHeight + aHeight; index++) {
        System.arraycopy(bytehead, 0, byteContent, index * (perline + 4), 4);
        System.arraycopy(nresult, index * perline, byteContent, 
          index * (perline + 4) + 4, perline);
      }

      return byteContent;
    }
    return null;
  }

  public void encodeYUV420SP(byte[] yuv420sp, int[] rgba, int width, int height)
  {
    int frameSize = width * height;

    int[] U = new int[frameSize];
    int[] V = new int[frameSize];
    int uvwidth = width / 2;

    int bits = 8;
    int index = 0;
    int f = 0;
    for (int j = 0; j < height; j++) {
      for (int i = 0; i < width; i++) {
        int r = (rgba[index] & 0xFF000000) >> 24;
        int g = (rgba[index] & 0xFF0000) >> 16;
        int b = (rgba[index] & 0xFF00) >> 8;

        int y = (66 * r + 129 * g + 25 * b + 128 >> 8) + 16;
        int u = (-38 * r - 74 * g + 112 * b + 128 >> 8) + 128;
        int v = (112 * r - 94 * g - 18 * b + 128 >> 8) + 128;

        byte temp = (byte)(y > 255 ? 255 : y < 0 ? 0 : y);
        yuv420sp[(index++)] = (byte) (temp > 0 ? 1 : 0);
      }

    }

    f = 0;
  }

  private class AcceptThread extends Thread
  {
    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread()
    {
      BluetoothServerSocket tmp = null;
      try
      {
        tmp = BlueToothService.this.adapter.listenUsingRfcommWithServiceRecord("BTPrinter", BlueToothService.MY_UUID);
      } catch (IOException e) {
        Log.e(BlueToothService.this.TAG, "listen() failed", e);
      }
      this.mmServerSocket = tmp;
    }

    public void run()
    {
      if (BlueToothService.this.D.booleanValue())
        Log.d(BlueToothService.this.TAG, "BEGIN mAcceptThread" + this);
      setName("AcceptThread");
      BluetoothSocket socket = null;

      while (BlueToothService.this.mState != 3) {
        try {
          socket = this.mmServerSocket.accept();
        } catch (IOException e) {
          break;
        }

        if (socket != null)
          synchronized (BlueToothService.this) {
            switch (BlueToothService.this.mState)
            {
            case 1:
            case 2:
              BlueToothService.this.connected(socket, socket.getRemoteDevice());
              break;
            case 0:
            case 3:
              try {
                socket.close();
              }
              catch (IOException localIOException1)
              {
              }
            }
          }
      }
    }

    public void cancel()
    {
      if (BlueToothService.this.D.booleanValue())
        Log.d(BlueToothService.this.TAG, "cancel " + this);
      try {
        this.mmServerSocket.close();
      } catch (IOException e) {
        Log.e(BlueToothService.this.TAG, "close() of server failed", e);
      }
    }
  }

  private class ConnectThread extends Thread
  {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;

    public ConnectThread(BluetoothDevice device)
    {
      this.mmDevice = device;
      BluetoothSocket tmp = null;
      try
      {
        tmp = device.createRfcommSocketToServiceRecord(BlueToothService.MY_UUID);
      } catch (IOException e) {
        Log.e(BlueToothService.this.TAG, "create() failed", e);
      }
      this.mmSocket = tmp;
    }

    public void run()
    {
      Log.i(BlueToothService.this.TAG, "BEGIN mConnectThread");
      setName("ConnectThread");

      BlueToothService.this.adapter.cancelDiscovery();
      BlueToothService.this.SetScanState(1);
      try
      {
        this.mmSocket.connect();
        BlueToothService.this.connectionSuccess();
      } catch (IOException e) {
        BlueToothService.this.connectionFailed();
        try
        {
          this.mmSocket.close();
        } catch (IOException e2) {
          Log.e(BlueToothService.this.TAG, 
            "unable to close() socket during connection failure", 
            e2);
        }

        BlueToothService.this.start();
        return;
      }

      synchronized (BlueToothService.this) {
        BlueToothService.this.mConnectThread = null;
      }

      BlueToothService.this.connected(this.mmSocket, this.mmDevice);
    }

    public void cancel() {
      try {
        this.mmSocket.close();
      } catch (IOException e) {
        Log.e(BlueToothService.this.TAG, "close() of connect socket failed", e);
      }
    }
  }

  private class ConnectedThread extends Thread
  {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;
    private boolean isCancle = false;

    public ConnectedThread(BluetoothSocket socket) {
      Log.d(BlueToothService.this.TAG, "create ConnectedThread");
      this.mmSocket = socket;
      InputStream tmpIn = null;
      OutputStream tmpOut = null;
      this.isCancle = false;
      try
      {
        tmpIn = socket.getInputStream();
        tmpOut = socket.getOutputStream();
      } catch (IOException e) {
        Log.e(BlueToothService.this.TAG, "temp sockets not created", e);
      }

      this.mmInStream = tmpIn;
      this.mmOutStream = tmpOut;
    }

    public void run()
    {
      Log.i(BlueToothService.this.TAG, "BEGIN mConnectedThread");

      while (!this.isCancle)
        try {
          byte[] buffer = new byte[1];

          int bytes = this.mmInStream.read(buffer);
          if (bytes > 0) {
            BlueToothService.this.SetPrinterType(2);

            if (buffer[0] != 17) {
              BlueToothService.this.SetWriteState(3);
            }
            else
            {
              BlueToothService.this.SetWriteState(2);
            }

          }
          else
          {
            Log.e(BlueToothService.this.TAG, "disconnected1");
            BlueToothService.this.connectionLost();
            this.isCancle = true;
          }

        }
        catch (IOException e)
        {
          Log.e(BlueToothService.this.TAG, "disconnected2", e);
          BlueToothService.this.connectionLost();
          this.isCancle = true;
        }
    }

    public void write(byte[] buffer)
    {
      try
      {
        this.mmOutStream.write(buffer);
        System.out.println("BTPWRITE====="+buffer);
        Log.i("BTPWRITE", new String(buffer, "GB2312"));

        BlueToothService.this.mHandler.obtainMessage(3, -1, -1, buffer)
          .sendToTarget();
      }
      catch (IOException localIOException) {
      }
    }

    public void cancel() {
      try {
        this.isCancle = true;
        this.mmSocket.close();
        Log.d(BlueToothService.this.TAG, "562cancel suc");
        BlueToothService.this.setState(1);
      } catch (IOException e) {
        Log.d(BlueToothService.this.TAG, "565cancel failed");
      }
    }
  }

  public static abstract interface OnReceiveDataHandleEvent
  {
    public abstract void OnReceive(BluetoothDevice paramBluetoothDevice);
  }
}